package com.infore.maintenance.main.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.infore.common.annotation.RecordLog;
import com.infore.common.constants.DataStatConstants;
import com.infore.common.exception.MyException;
import com.infore.common.model.dto.TreeDto;
import com.infore.common.model.entity.TBaseDatasource;
import com.infore.common.response.ApiResponse;
import com.infore.common.utils.EncryptAESUtil;
import com.infore.common.utils.StringUtils;
import com.infore.maintenance.main.dao.TBaseDatasourceMapper;
import com.infore.maintenance.main.service.TBaseDatasourceService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.infore.metadata.core.enums.DatabaseEnum;
import com.infore.metadata.core.model.ColumnModel;
import com.infore.metadata.core.model.MetadataConfig;
import com.infore.metadata.core.model.SimpleDataSource;
import com.infore.metadata.core.model.TableModel;
import com.infore.metadata.core.service.MetadataQueryHandle;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据源 服务实现类
 * </p>
 *
 * @author lijh
 * @since 2022-12-20
 */
@Service
@RecordLog(descript = "数据源操作")
public class TBaseDatasourceServiceImpl extends ServiceImpl<TBaseDatasourceMapper, TBaseDatasource> implements TBaseDatasourceService {


    @Override
    public SimpleDataSource getDatabaseConnect(TBaseDatasource tbasedatasource){
        SimpleDataSource simpleDataSource =null;
        DatabaseEnum databaseEnum = null;
        if("ORACLE".equals(tbasedatasource.getDatabaseType().toUpperCase())){
            databaseEnum = DatabaseEnum.ORACLE;
        }else if("MYSQL".equals(tbasedatasource.getDatabaseType().toUpperCase())){
            databaseEnum = DatabaseEnum.MYSQL;
        }else{
            throw new MyException("500",tbasedatasource.getDatabaseType()+"数据库类型不存在");
        }
        try {
            simpleDataSource = new SimpleDataSource(databaseEnum,
                    tbasedatasource.getJdbcUrl(),
                    tbasedatasource.getJdbcUsername(),
                    tbasedatasource.getJdbcPassword()
            );
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException("500",tbasedatasource.getDatabaseSchema()+"数据库连接异常",e.getMessage());
        }
        return simpleDataSource;
    }


    @Override
    public List<TreeDto> getDatasourcesGroupByDatabaseType(String tableName){
        List<TreeDto> result = new ArrayList<>();
        Wrapper<TBaseDatasource> wrapper = new EntityWrapper<TBaseDatasource>();
        wrapper.eq("del_state", 0);
        List<TBaseDatasource> list = this.selectList(wrapper);
        Map<String, List<TBaseDatasource>> group = list.stream().collect(Collectors.groupingBy(g -> g.getDatabaseType()));
        for(Map.Entry<String,List<TBaseDatasource>>  entry : group.entrySet()){
            String key = entry.getKey();
            List<TBaseDatasource> value = entry.getValue();
            TreeDto tree = new TreeDto();
            tree.setLabel(key);
            List<TreeDto> childs = new ArrayList<>();
            for (TBaseDatasource datasource:value) {
                TreeDto child = new TreeDto();
                child.setId(datasource.getId());
                child.setCode(datasource.getDatabaseCode());
                child.setLabel(datasource.getDatabaseName());
                child.setChildren(getTables(datasource,tableName));
                child.setRemark(datasource.getDatabaseSchema());
                childs.add(child);
            }
            tree.setChildren(childs);
            result.add(tree);
        }
        return result;
    }
    @Override
    public List<TreeDto> getDatasourcesAllTableInfo(String tableName){
        List<TreeDto> result = new ArrayList<>();
        Wrapper<TBaseDatasource> wrapper = new EntityWrapper<TBaseDatasource>();
        wrapper.eq("del_state", 0);
        List<TBaseDatasource> list = this.selectList(wrapper);
        Map<String, List<TBaseDatasource>> group = list.stream().collect(Collectors.groupingBy(g -> g.getDatabaseType()));
        for(Map.Entry<String,List<TBaseDatasource>>  entry : group.entrySet()){
            String key = entry.getKey();
            List<TBaseDatasource> value = entry.getValue();
            TreeDto tree = new TreeDto();
            tree.setLabel(key);
            List<TreeDto> childs = new ArrayList<>();
            for (TBaseDatasource datasource:value) {
                TreeDto child = new TreeDto();
                child.setId(datasource.getId());
                child.setCode(datasource.getDatabaseCode());
                child.setLabel(datasource.getDatabaseName());
                child.setRemark(datasource.getDatabaseSchema());
                child.setChildren(getTablesAndColumns(datasource,tableName));
                childs.add(child);
            }
            tree.setChildren(childs);
            result.add(tree);
        }
        return result;
    }

    @Override
    public List<TableModel> getTablesColumns(String databaseCode,String tableName) {
        Wrapper<TBaseDatasource> wrapper = new EntityWrapper<TBaseDatasource>();
        wrapper.eq("database_code", databaseCode);
        List<TBaseDatasource> schemaList = this.selectList(wrapper);
        if(schemaList==null ||schemaList.size()==0){
            return null;
        }
        TBaseDatasource schema = schemaList.get(0);
        try {
            String dePassword = EncryptAESUtil.aesDecrypt(schema.getJdbcPassword(),DataStatConstants.AES_KEY_PASSWORD);
            schema.setJdbcPassword(dePassword);
        } catch (Exception e) {
            e.printStackTrace();
        }

        SimpleDataSource simpleDataSource = getDatabaseConnect(schema);
        List<TableModel> tableModels = null;
        // 非必要，按需配置
        MetadataConfig metadataConfig = new MetadataConfig();
        //匹配过滤查询的ORACLE用户，不指定用户会查询整个库的数据
        metadataConfig.setSchemaPattern("%"+schema.getDatabaseSchema()+"%");
        if(StringUtils.isNotEmpty(tableName)){
            //匹配过滤查的表名
            metadataConfig.setTableNamePattern("%"+tableName+"%");
        }
        MetadataQueryHandle metadataQueryHandle = new MetadataQueryHandle();
        try {
            tableModels = metadataQueryHandle.queryTablesColumnsCoreHandle(simpleDataSource, metadataConfig);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                simpleDataSource.closeConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return tableModels;
    }


    public List<TreeDto> getTables(TBaseDatasource schema,String tableName) {
        List<TreeDto> result = new ArrayList<>();
        try {
            String dePassword = EncryptAESUtil.aesDecrypt(schema.getJdbcPassword(),DataStatConstants.AES_KEY_PASSWORD);
            schema.setJdbcPassword(dePassword);
        } catch (Exception e) {
            e.printStackTrace();
        }
        SimpleDataSource simpleDataSource = getDatabaseConnect(schema);
        List<TableModel> tableModels = null;
        // 非必要，按需配置
        MetadataConfig metadataConfig = new MetadataConfig();
        //匹配过滤查询的ORACLE用户，不指定用户会查询整个库的数据
        metadataConfig.setSchemaPattern("%"+schema.getDatabaseSchema()+"%");
        if(StringUtils.isNotEmpty(tableName)){
            //匹配过滤查的表名
            metadataConfig.setTableNamePattern("%"+tableName+"%");
        }
        MetadataQueryHandle metadataQueryHandle = new MetadataQueryHandle();
        try {
            tableModels = metadataQueryHandle.queryTablesCoreHandle(simpleDataSource, metadataConfig);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                simpleDataSource.closeConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        for (TableModel table:tableModels) {
            TreeDto tree = new TreeDto();
            tree.setLabel(table.getTableName());
            tree.setCode(schema.getDatabaseCode());
            tree.setRemark(table.getRemarks());
            result.add(tree);
        }
        return result;
    }


    public List<TreeDto> getTablesAndColumns(TBaseDatasource schema,String tableName) {
        List<TreeDto> result = new ArrayList<>();
        try {
            String dePassword = EncryptAESUtil.aesDecrypt(schema.getJdbcPassword(),DataStatConstants.AES_KEY_PASSWORD);
            schema.setJdbcPassword(dePassword);
        } catch (Exception e) {
            e.printStackTrace();
        }
        SimpleDataSource simpleDataSource = getDatabaseConnect(schema);
        List<TableModel> tableModels = null;
        // 非必要，按需配置
        MetadataConfig metadataConfig = new MetadataConfig();
        //匹配过滤查询的ORACLE用户，不指定用户会查询整个库的数据
        metadataConfig.setSchemaPattern("%"+schema.getDatabaseSchema()+"%");
        if(StringUtils.isNotEmpty(tableName)){
            //匹配过滤查的表名
            metadataConfig.setTableNamePattern("%"+tableName+"%");
        }
        MetadataQueryHandle metadataQueryHandle = new MetadataQueryHandle();
        try {
            tableModels = metadataQueryHandle.queryTablesColumnsCoreHandle(simpleDataSource, metadataConfig);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                simpleDataSource.closeConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        for (TableModel table:tableModels) {
            TreeDto tree = new TreeDto();
            tree.setLabel(table.getTableName());
            tree.setCode(schema.getDatabaseCode());
            tree.setRemark(table.getRemarks());

            List<TreeDto> childs = new ArrayList<>();
            List<ColumnModel> columnModelList = table.getColumnModelList();
            for (ColumnModel col:columnModelList) {
                TreeDto child = new TreeDto();
                child.setLabel(col.getColumnName());
                child.setRemark(col.getRemarks());
                childs.add(child);
            }
            tree.setChildren(childs);
            result.add(tree);
        }
        return result;
    }

}
